﻿
using System.Security.Cryptography;
using System.Text;

using Demo.DemoFeature.ApiModels.Users;
using Demo.DemoFeature.DBModels;

using GCC.APIContainer.Auth.Attributes;
using GCC.APIContainer.Utilities;
using GCC.Container.Abstracts;
using GCC.Container.Models;

using Microsoft.AspNetCore.Mvc;

namespace Demo.DemoFeature
{
    [ApiController]
    [Route("Demo")]
    public class UsersController : GCCAPIControllerBase
    {
        public UsersController(AbsGCCContext context) : base(context)
        {
        }

        [HttpDelete("users/token/classic")]
        [GCCAuth(allowOffline: false)]
        public async Task Logout()
        {
            _ = HttpContext.Request.Headers.TryGetValue(GCCContext.GetAuthHeaderKey(), out var token);
            await GCCContext.Logout(token);
        }

        [HttpPost("users/token/classic")]
        public async Task<DataResponse<CreateTokenResponse>> CreateToken([FromBody] CreateTokenRequest request)
        {
            if (request is null || string.IsNullOrWhiteSpace(request.UserName) || string.IsNullOrWhiteSpace(request.Passwords))
            {
                return IllegalRequest<CreateTokenResponse>();
            }
            var result = await GCCContext.Login(new GCCLoginRequest()
            {
                OpenKey = request.UserName,
                Type = 0,
                Token = Md5(request.Passwords),
                CacheSecond = 60 * 5
            });
            if (string.IsNullOrWhiteSpace(result))
            {
                return IllegalRequest<CreateTokenResponse>();
            }
            var userInfo = await GCCContext.GetUserByToken(result);
            if (userInfo is null)
            {
                return IllegalRequest<CreateTokenResponse>();
            }
            if (userInfo.UID == 1)
            {
                return HandleData(new CreateTokenResponse()
                {
                    Token = result,
                    UserName = "admin"
                });
            }
            var userBaseInfo = GCCEntrance.DBManager!.LocalDB!.Select<DemoUserBaseInfos>(userInfo.UID).First();
            if (userBaseInfo is null || userBaseInfo.State != 0)
            {
                return IllegalRequest<CreateTokenResponse>();
            }
            return HandleData(new CreateTokenResponse()
            {
                Token = result,
                UserName = userBaseInfo.UserName
            });
        }

        [HttpGet("users/items")]
        [GCCAuth(allowOffline: true, roles: new string[] { "admin" })]
        public DataResponse<List<GetAllUserResponse>> GetAllUser([FromQuery] GetAllUserRequest request)
        {
            var dbres = GCCEntrance.DBManager!.LocalDB!.Select<DemoUserBaseInfos>()
                .WhereIf(!string.IsNullOrWhiteSpace(request.SearchKey), item => item.UserName.Contains(request.SearchKey!))
                .Count(out var count)
                .Page(request.PageIndex ?? 1, request.PageSize)
                .ToList();
            return HandleData(dbres.Select(item => new GetAllUserResponse()
            {
                UID = item.UID,
                UserName = item.UserName,
                State = item.State,
            }).ToList(), count);
        }

        [HttpPost("users/items")]
        [GCCAuth(allowOffline: false, roles: new string[] { "admin" })]
        public DataResponse<bool> CreateUser([FromBody] CreateUserRequest request)
        {
            var saveRes = false;
            _ = HttpContext.Request.Headers.TryGetValue(GCCContext.GetAuthHeaderKey(), out var token);
            GCCEntrance.DBManager!.LocalDB!.Transaction(() =>
            {
                var userInfo = new DemoUserBaseInfos()
                {
                    UID = LuanNiao.Core.IDGen.GetInstance().NextId(),
                    UserName = request.Name
                };
                var loginInfo = new GCCUserLoginInfos()
                {
                    UID = userInfo.UID,
                    OpenKey = request.OpenKey,
                    Token = Md5(request.Password),
                    Type = 0
                };
                var res = GCCContext.SetUser(loginInfo, token).Result;
                if (!res)
                {
                    throw new Exception();
                }
                if (GCCEntrance.DBManager!.LocalDB!.Insert(userInfo).ExecuteAffrows() != 1)
                {
                    throw new Exception();
                }
                saveRes = true;
            });
            return HandleData(saveRes);
        }

        [HttpDelete("users/items/{uid}")]
        [GCCAuth(allowOffline: false, roles: new string[] { "admin" })]
        public DataResponse<bool> StopLogin([FromRoute] long uid)
        {
            var res = GCCEntrance.DBManager!.LocalDB!.Update<DemoUserBaseInfos>(uid)
                .Set(item => item.State, 1).ExecuteAffrows() == 1;
            return HandleData(res);
        }

        [HttpPatch("users/items/{uid}/LoginState")]
        [GCCAuth(allowOffline: false, roles: new string[] { "admin" })]
        public DataResponse<bool> ReLogin([FromRoute] long uid)
        {
            var res = GCCEntrance.DBManager!.LocalDB!.Update<DemoUserBaseInfos>(uid)
                .Set(item => item.State, 0).ExecuteAffrows() == 1;
            return HandleData(res);
        }




        private static string Md5(string txt)
        {
            byte[] sor = Encoding.UTF8.GetBytes(txt);
            using MD5 md5 = MD5.Create();
            byte[] result = md5.ComputeHash(sor);
            StringBuilder strbul = new(40);
            for (int i = 0; i < result.Length; i++)
            {
                //加密结果"x2"结果为32位,"x3"结果为48位,"x4"结果为64位
                _ = strbul.Append(result[i].ToString("x2"));
            }
            return strbul.ToString();
        }
    }
}
